<?php
namespace catchAdmin\system\controller;

use catchAdmin\permissions\model\Permissions;
use catcher\base\CatchController;
use catcher\CatchResponse;
use catcher\exceptions\FailedException;
use catcher\generate\CreateModule;
use catcher\generate\Generator;
use think\facade\Console;
use think\facade\Log;
use think\Request;

class  Generate extends CatchController
{
    public function save(Request $request, Generator $generator)
    {
        $formjson = $request->param('data') ;
        $params = json_decode($formjson, true);
        //创建CRUD表单页面
        if($params['create_crudform']){
            Console::call('create:elmform', [$params['controller']['table'],'-m',$params['controller']['module'],'-j',$formjson]);
        }
        $result = $generator->done($request->param());

        //自动创建默认菜单
        if($params['create_menu']){
            $this->autoCreateMenu($params);
        }

        return CatchResponse::success($result);
    }

    /**
     * 预览
     *
     * @time 2020年04月29日
     * @param Request $request
     * @param Generator $generator
     * @return \think\response\Json
     */
    public function preview(Request $request, Generator $generator)
    {
        return CatchResponse::success($generator->preview($request->param()));
    }


    public function createModule(Request $request, CreateModule $module)
    {
        return CatchResponse::success($module->generate($request->post()));
    }

    //自动生成菜单
    public function autoCreateMenu($params)
    {
        try {
            [$root, $module, $c, $controller] = explode('\\', $params['controller']['controller']);

            $permission = Permissions::where('module', $module)
                ->where('parent_id', 0)->find();

            $permissionModel = app()->make(Permissions::class);
            //是否存在模块菜单
            if (!$permission) {
                $moduleMenuId = $permissionModel->createBy([
                    'permission_name' => $module, //module名作为默认控制器菜单名
                    'module' => $module,
                    'parent_id' => 0,
                    'level' => 1,
                    'route' => '/'.$module, //module名作为默认前端路由
                    'creator_id' => 1,
                    'method' => 'get',
                    'permission_mark' => $module,
                    'component' => 'layout', //layout作为module默认前端组件
                ]);
            } else {
                $moduleMenuId = $permission->id;
            }
            // /module/controller/curd 作为默认前端路由
            $controllerRoute = '/'.$module.'/'.lcfirst($controller).'/'.'curd';

            // 控制器菜单是否已经建立
            $hasMenu = Permissions::where('module', $module)
                ->where('permission_mark', lcfirst($controller))->where('route',$controllerRoute)->find();
            if (!$hasMenu) {
                $id = $permissionModel->createBy([
                    'permission_name' => lcfirst($controller), //controller名作为默认控制器菜单名
                    'module' => $module,
                    'parent_id' => $moduleMenuId,
                    'level' => $moduleMenuId,
                    'route' => $controllerRoute,
                    'creator_id' => 1,
                    'method' => 'get',
                    'permission_mark' => lcfirst($controller),
                    'component' => $params['controller']['module'].'_'.lcfirst($controller), //vue-replace-module_vue-replace-controller作为controller默认前端组件
                ]);
            } else {
                $id = $hasMenu->id;
            }

            $reflectClass = new \ReflectionClass(app()->make($params['controller']['controller']));

            $exceptMethods = $this->getExceptionMethods($reflectClass);

            $methods = $this->getCurrentControllerMethods($reflectClass);

            $initMethods = $this->initMethods();

            //方法权限节点
            foreach ($methods as $method) {
                if (!in_array($method, $exceptMethods)) {
                    $hasInit = $initMethods[$method] ?? false;
                    // 如果已经存在 直接跳过
                    if (Permissions::where('module', $module)
                        ->where('permission_mark', lcfirst($controller) . '@' . $method)->find()) {
                        continue;
                    }
                    $data = [
                        'level' => $moduleMenuId . '-' .$id,
                        'permission_mark' => lcfirst($controller) . '@' . $method,
                        'parent_id' => $id,
                        'module' => $module,
                        'type' => Permissions::BTN_TYPE,
                        'creator_id' => 1,
                        'sort' => 1,
                    ];
                    if (!$hasInit) {
                        $name = $method; //method默认作为菜单名
                        $data['permission_name'] = $name;
                    } else {
                        [$name, $httpMethod] = $initMethods[$method];
                        $data['permission_name'] = $name;
                        $data['method'] = $httpMethod;
                    }

                    $permissionModel->createBy($data);
                }
            }
            return true;

        } catch (\Exception $e) {
            throw new FailedException($e->getMessage());
        }
    }

    /**
     * 获取 except 方法
     *
     * @time 2020年05月08日
     * @param \ReflectionClass $class
     * @return array
     */
    protected function getExceptionMethods(\ReflectionClass $class)
    {
        $methods = [];

        $methods[] = '__construct';

        foreach ($class->getParentClass()->getMethods() as $method) {
            $methods[] = $method->getName();
        }

        return $methods;
    }

    /**
     * 获取当前控制器的方法
     *
     * @time 2020年05月08日
     * @param \ReflectionClass $class
     * @return array
     */
    protected function getCurrentControllerMethods(\ReflectionClass $class)
    {
        $methods = [];

        foreach ($class->getMethods() as $method) {
            $methods[] = $method->getName();
        }

        return $methods;
    }

    /**
     * 初始化方法
     *
     * @time 2020年05月08日
     * @return \string[][]
     */
    protected function initMethods()
    {
        return [
            'index' => ['列表', 'get'],
            'save'  => ['保存', 'post'],
            'read'  => ['读取', 'get'],
            'update' => ['更新', 'put'],
            'delete' => ['删除', 'delete'],
        ];
    }
}
